package com.siki.controller.file;

import io.swagger.annotations.Api;
import org.apache.logging.log4j.util.Strings;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Siki
 * @Date 2020/4/23
 *
 * @Desc: 简单粗暴的文件上传下载，可惜不实用，废弃了
 */
@SuppressWarnings("JavadocReference")
@RestController
@Api(tags = "Sai哥的教学式文件上传 - 略过")
@Deprecated
public class MultipartController {

    // 上传单个文件
    @PostMapping("/upload1")
    public String uploadFileSingle(@RequestParam("uploader") String username,// @RequestParam 从body里读取相应名称的段的数据
                                   @RequestParam("logo") MultipartFile file) throws IOException {

        if (!file.isEmpty()) {
            // 定义写入文件的路径,注意：必须是 绝对路径，不能是相对路径。
            File file1 = new File("/Users/qizai/Desktop/" + file.getOriginalFilename());
            // 复制数据到新文件。
            Files.copy(file.getInputStream(), file1.toPath(), StandardCopyOption.REPLACE_EXISTING);

            return "上传文件成功!" + "上传者：" + username + ",文件名：" + file.getOriginalFilename();
        }

        return "上传文件失败";
    }

    // 同时上传多个文件，并带文本域。
    @PostMapping("upload2")
    public String uploadFileMulti(@RequestParam("uploader") String username,// @RequestParam 从body里读取相应名称的段的数据，这里是文本段。
                                  @RequestParam("files") List<MultipartFile> images) { // 同时上传多个文件时，文件段的name属性设置同一个，这样同一名称的文件段解释为List注入。

        ArrayList<String> filenames = new ArrayList<>();

        if (!images.isEmpty()) {
            images.forEach(file -> {
                // 定义写入文件的路径,注意：必须是 绝对路径，不能是相对路径。
                File file1 = new File("/Users/sai/git/" + file.getOriginalFilename());
                // 复制数据到新文件。
                try {
                    Files.copy(file.getInputStream(), file1.toPath(), StandardCopyOption.REPLACE_EXISTING);
                    filenames.add(file.getOriginalFilename());
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("保存文件失败！");
                }
            });

            return "上传文件成功!" + "上传者：" + username + ",文件名：" + Strings.join(filenames,',');
        }
        else
            return "上传文件失败！上传文件为空。";
    }

    /**
     * 下载并在浏览器显示文件内容
     * 测试地址：http://localhost:8080/download
     *
     * {@link UrlResource} 可以获取 本地文件 或 外网文件。如果是本地文件需要加 file: 协议头。
     *
     * 前往下面方法，查看mvc是如何查找支持{@link Resource}类型的返回值处理器的:
     * @see HandlerMethodReturnValueHandlerComposite#selectHandler(java.lang.Object, org.springframework.core.MethodParameter)
     *
     * 经断点调试知道，最后是由{@link RequestResponseBodyMethodProcessor}处理返回值的。
     * 它并不是根据返回值的类型匹配的，只是其它的都不支持，而{@link RequestResponseBodyMethodProcessor}只判断方法有没有{@link org.springframework.web.bind.annotation.ResponseBody}注解。
     * {@link RequestResponseBodyMethodProcessor} 使用 {@link ResourceHttpMessageConverter}http信息转换器，完成把{@link Resource}对象转换为 Http响应体 的写入操作。
     *
     * 注意：{@link AbstractMessageConverterMethodProcessor} 会根据 {@link RequestMapping#produces()}的值 设置 http响应的Content-Type，浏览器会根据http响应的Content-Type决定如何渲染返内容。
     * 如果是图片的字节流数据，不能设置为text/html,否则会显示乱码；要指定图片的具体类型，如{@link MediaType#IMAGE_PNG_VALUE},这样浏览器才能正确渲染图片。
     *
     * 说明：当在浏览器访问本接口时，浏览器会直接显示图片，而不会提示下载的对话框。
     *
     * @return {@link Resource}
     * @throws MalformedURLException 异常
     */
    @GetMapping(value = "download", produces = MediaType.IMAGE_PNG_VALUE)
    public Resource download() throws MalformedURLException {

        return new UrlResource("https://www.baidu.com/img/baidu_resultlogo@2.png");
//        return new UrlResource("file:/Users/sai/Pictures/banner.png");// 如果是本地文件，需要加 file: 协议。
    }

    /**
     * http://localhost:8080/download1
     *
     * 会提示下载的对话框，不会直接在浏览器渲染文件内容。
     *
     * 注意：http响应的contentType设置为{@link MediaType.APPLICATION_OCTET_STREAM}也会提示下载对话框。
     *
     * 这里同学们思考一下，是否可以通过{@link UrlResource}调用云存储的api获取文件，从而实现转发？？
     */
    @GetMapping(value = "download1", produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<Resource> download1() throws MalformedURLException {

//        UrlResource urlResource = new UrlResource("https://www.baidu.com/img/baidu_resultlogo@2.png");
        UrlResource urlResource = new UrlResource("file:/Users/sai/Pictures/banner.png");// 如果是本地文件，需要加 file: 协议。

        return ResponseEntity.ok()
//                            .contentType(MediaType.APPLICATION_OCTET_STREAM) // 在这里直接写Content-Type也可以。
                .header(HttpHeaders.CONTENT_DISPOSITION,"attachment; filename=\"" + urlResource.getFilename() + "\"") // 可以在header里修改为自定义的下载文件的名字，不需要与原文件名相同。
                .body(urlResource);
    }
}